package cn.jiahua.hospital.controller;

import ch.qos.logback.core.net.SyslogOutputStream;
import cn.jiahua.hospital.config.WxConfig;
import cn.jiahua.hospital.constants.Constants;
import cn.jiahua.hospital.dto.Result;
import cn.jiahua.hospital.exceptions.RedisException;
import cn.jiahua.hospital.exceptions.TokenProtectedException;
import cn.jiahua.hospital.mapper.UserMapper;
import cn.jiahua.hospital.pojo.User;
import cn.jiahua.hospital.service.TokenService;
import cn.jiahua.hospital.service.UserService;
import cn.jiahua.hospital.utils.HttpClientUtil;
import cn.jiahua.hospital.utils.RedisUtil;
import cn.jiahua.hospital.utils.ResultUtils;
import cn.jiahua.hospital.vo.TokenVo;
import cn.jiahua.hospital.vo.WxTokenVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @ClassName WxController
 * @Description TODO
 * @Author yaozhaobao
 * @Date 2021/4/7 11:25
 * @Version 1.0
 **/
@Api(tags = "微信登录")
@RestController
@RequestMapping("/api/user")
public class WxController {
    @Autowired
    WxConfig wxConfig;

    @Autowired
    TokenService tokenService;

    @Autowired
    UserService userService;


    @Autowired
    RedisUtil redisUtil;

    @Autowired
    RedisTemplate redisTemplate;

    @ApiOperation(value = "wx登录请求", produces = "application/json", notes = "wx登录请求")
    //1.跳转到二维码授权页面的接口
    @GetMapping("/login/wechat")
    public Result redirectWx(HttpServletResponse response) throws IOException {
        StringBuffer url = new StringBuffer("https://open.weixin.qq.com/connect/qrconnect?appid=").
                append(wxConfig.getAppid())
                .append("&redirect_uri=")
                .append(URLEncoder.encode("http://localhost:8080/hospital/api/user/callback"))
                .append("&response_type=code&scope=snsapi_login&state=hellowx#wechat_redirect");

        return ResultUtils.returnDataSuccess(url.toString());
    }


    //2.用户授权后，回调的接口---code

    @GetMapping("/callback")
    public Result callback(String code, String state, HttpServletResponse response2, HttpServletRequest request) throws IOException {

        if (state == null || !state.equals("hellowx")) {
            ResultUtils.returnFail("非法请求");
        }
        //临时票据
        StringBuffer stringBuffer = new StringBuffer("https://api.weixin.qq.com/sns/oauth2/access_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&secret=");
        stringBuffer.append(wxConfig.getAppsecret());
        stringBuffer.append("&code=");
        stringBuffer.append(code);
        stringBuffer.append("&grant_type=authorization_code");
        String response = HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject = JSONObject.parseObject(response);
        System.out.println(jsonObject);
        //1.判断接口是否能正确调用获取accesstoken
        if (jsonObject.get("errorCode") != null) {
            //说明出错，调用接口出错
            ResultUtils.returnFail((String) jsonObject.get("errmsg"), (String) jsonObject.get("errorCode"));
        }

        //2.判断当前openId是否存在在数据中，若不存在则需要插入数据实现注册功能
        Map map = new HashMap<String, Object>();
        map.put("userWeChatOpenId", (String) jsonObject.get("openid"));
        List<User> userList = userService.getUserListByMap(map);
        System.out.println(userList);
        User user = new User();
        if (userList == null || userList.size() == 0) {
            user.setUserWeChatOpenId((String) jsonObject.get("openid"));
        } else {
            user = userList.get(0);
            if (user.getBlacklist() == 1) {
                response2.sendRedirect("/hospital/page/login.html?block="+"no");
                return ResultUtils.returnFail("当前账号被拉黑无法登录");
            }
        }

        //3.生成本站的token，保存用户的登录信息。
        TokenVo tokenVo = tokenService.genenrateToken(user);

        //5.返回token
        WxTokenVo wxTokenVo = new WxTokenVo();
        wxTokenVo.setTokenVo(tokenVo);
        wxTokenVo.setAccessToken((String) jsonObject.get("access_token"));
        wxTokenVo.setRefreshToken((String) jsonObject.get("refresh_token"));
        wxTokenVo.setExpiresTime(jsonObject.get("expires_in").toString());
        wxTokenVo.setOpenId((String) jsonObject.get("openid"));
        Set<String> adminTokens2 =redisTemplate.keys("wx:token"+"*");
        String phone=user.getUserPhone();
        for(Object adminToken2 :adminTokens2){
            String token = adminToken2.toString().substring(adminToken2.toString().indexOf("-")+22,adminToken2.toString().length());
            if(token.equals(phone)){
                redisUtil.del(adminToken2.toString());
            }
        }

        redisUtil.set("wx:" + tokenVo.getToken(), wxTokenVo, Constants.Token.WX_VALID_TIME);
        //拼接url请求请求用户数据接口
        StringBuffer stringBuffer1 = new StringBuffer("https://api.weixin.qq.com/sns/userinfo?access_token=");
        stringBuffer1.append(wxTokenVo.getAccessToken());
        stringBuffer1.append("&openid=");
        stringBuffer1.append(wxTokenVo.getOpenId());
        String response1 = HttpClientUtil.doGet(stringBuffer1.toString());
        JSONObject jsonObject1 = JSONObject.parseObject(response1);
        //判断返回响应数据是否正确

        if (jsonObject1.get("errcode") != null) {
            return ResultUtils.returnFail(jsonObject1.get("errmsg").toString(), jsonObject1.get("errcode").toString());
        }
        System.out.println(user.getUserWeChatName());
        if (user.getUserWeChatName() == null) {
            System.out.println("第一次登录");
            response2.sendRedirect("/hospital/page/forget_pwd.html?wxtoken="+"wx:" + tokenVo.getToken());
            return ResultUtils.returnDataSuccess(user);
        } else {
            //4.保存token到redis中
            Set<String> adminTokens =redisTemplate.keys("token"+"*");
            for(Object adminToken1 :adminTokens){
                String token = adminToken1.toString().substring(adminToken1.toString().indexOf("-")+22,adminToken1.toString().length());

                if(token.equals(phone)){
                    redisUtil.del(adminToken1.toString());
                }
            }

            tokenService.saveToken(tokenVo.getToken(), user);
            System.out.println("非第一次登录");
            //response2.sendRedirect("/hospital/api/user/hello?token="+tokenVo.getToken());
            response2.sendRedirect("/hospital/page/home.html?token="+tokenVo.getToken());
            return ResultUtils.returnSuccess("登录成功",40010);
        }
    }

    @GetMapping("/hello")
    public void hello(String token,HttpServletRequest request,HttpServletResponse response){
        System.out.println(token);
        try {
            response.setHeader("token",token);
            //request.getRequestDispatcher("/page/home.html").forward(request,response);
            response.sendRedirect("/hospital/page/home.html");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * accesstoken的置换
     *
     * @param token
     * @return
     */
    @ApiOperation(value = "wx置换token", produces = "application/json", notes = "wx置换token")
    @PostMapping(value = "/refresh")
    public Result refreshWechatToken(@RequestHeader String token) {

        //1.查看token是否有效，token到了置换期，则先重新生成token
        TokenVo tokenVo = null;
        try {
            tokenVo = tokenService.refreshToken(token);
        } catch (RedisException e) {
            e.printStackTrace();
        } catch (TokenProtectedException e) {
            e.printStackTrace();
        }
        WxTokenVo wxTokenVo = (WxTokenVo) redisUtil.get("wx:" + token);
        //2.置换accessToken
        StringBuffer stringBuffer = new StringBuffer("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&grant_type=");
        stringBuffer.append("refresh_token");
        stringBuffer.append("&refresh_token=");
        stringBuffer.append(wxTokenVo.getRefreshToken());
        String response = HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject = JSON.parseObject(response);
        if (jsonObject.get("error") != null) {
            return ResultUtils.returnFail(jsonObject.get("errmsg").toString(), jsonObject.get("error").toString());
        }
        wxTokenVo.setRefreshToken(jsonObject.get("refresh_token").toString());
        wxTokenVo.setAccessToken(jsonObject.get("access_token").toString());
        redisUtil.expire("wx:" + token, 30);
        redisUtil.set("wx:" + tokenVo.getToken(), wxTokenVo, Constants.Token.WX_VALID_TIME);
        return ResultUtils.returnDataSuccess(tokenVo);
    }

    @ApiOperation(value = "通过wxtoken绑定手机号码", produces = "application/json", notes = "通过wxtoken绑定手机号码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "wxtoken", value = "wxtoken", required = true, dataType = "String"),
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "String"),
    })
    //1.跳转到二维码授权页面的接口
    @GetMapping("/login/wetoken")
    public Result loginWxtoken(String wxtoken,
                               String phone,
                               HttpServletResponse response) throws UnsupportedEncodingException {
        User user =new User();
        WxTokenVo wxtoken2 = (WxTokenVo) redisTemplate.opsForValue().get(wxtoken);
        StringBuffer stringBuffer1 = new StringBuffer("https://api.weixin.qq.com/sns/userinfo?access_token=");
        stringBuffer1.append(wxtoken2.getAccessToken());
        stringBuffer1.append("&openid=");
        stringBuffer1.append(wxtoken2.getOpenId());
        String response1 = HttpClientUtil.doGet(stringBuffer1.toString());
        JSONObject jsonObject1 = JSONObject.parseObject(response1);
        String nickname = new String(jsonObject1.get("nickname").toString().getBytes("ISO-8859-1"), "UTF-8");
        user.setUserWeChatName(nickname);
        user.setUserSex(Integer.parseInt(jsonObject1.get("sex").toString()));
        user.setUserWeChatHead(jsonObject1.get("headimgurl").toString());
        user.setWxBindTime(new Date());
        user.setUserRole(0);
        user.setUserPhone(phone);
        user.setUserWeChatOpenId(wxtoken2.getOpenId());
        int i=userService.qdtxAddUser(user);
        if(i!=0){
            Set<String> adminTokens2 =redisTemplate.keys("wx:token"+"*");
            String phone2=user.getUserPhone();
            Map map=new HashMap();
            map.put("userPhone",phone2);
            List<User> userList = userService.getUserListByMap(map);
            if(userList!=null&&userList.size()>0){
                user=userList.get(0);
                String openid = user.getUserWeChatOpenId();
            for(Object adminToken2 :adminTokens2){
                String wxtoken4 = adminToken2.toString().substring(adminToken2.toString().indexOf("-")+22,adminToken2.toString().length());
                System.out.println(wxtoken4);
                if(wxtoken4.equals(openid)){
                    redisUtil.del(adminToken2.toString());
                }
            }
            }
            TokenVo tokenVo = tokenService.genenrateToken(user);
            redisUtil.set("wx:" + tokenVo.getToken(), wxtoken2, Constants.Token.WX_VALID_TIME);
            tokenService.saveToken(tokenVo.getToken(), user);
            response.setHeader("token", tokenVo.getToken());
            return  ResultUtils.returnSuccess("绑定成功",41000);
        }
        return  ResultUtils.returnFail("绑定失败");
    }
}
